//===================================================================================
// Microsoft patterns & practices
// Composite Application Guidance for Windows Presentation Foundation and Silverlight
//===================================================================================
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===================================================================================
using System.ComponentModel;
using System.Windows;
using Windows.UI.Xaml;

namespace Microsoft.Practices.Prism
{
	/// <summary>
	/// Class that wraps an object, so that other classes can notify for Change events. Typically, this class is set as 
	/// a Dependency Property on DependencyObjects, and allows other classes to observe any changes in the Value. 
	/// </summary>
	/// <remarks>
	/// This class is required, because in Silverlight, it's not possible to receive Change notifications for Dependency properties that you do not own. 
	/// </remarks>
	/// <typeparam name="T">The type of the property that's wrapped in the Observable object</typeparam>
	public class ObservableObject<T> : FrameworkElement, INotifyPropertyChanged
	{
		/// <summary>
		/// Identifies the Value property of the ObservableObject
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This is the pattern for WPF dependency properties")]
		public static readonly DependencyProperty ValueProperty =
				DependencyProperty.Register("Value", typeof(T), typeof(ObservableObject<T>), new PropertyMetadata(default(T), ValueChangedCallback));

		/// <summary>
		/// Event that gets invoked when the Value property changes. 
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;

		/// <summary>
		/// The value that's wrapped inside the ObservableObject.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
		public T Value
		{
			get { return (T)this.GetValue(ValueProperty); }
			set { this.SetValue(ValueProperty, value); }
		}

		private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			ObservableObject<T> thisInstance = ((ObservableObject<T>)d);
			PropertyChangedEventHandler eventHandler = thisInstance.PropertyChanged;
			if (eventHandler != null)
			{
				eventHandler(thisInstance, new PropertyChangedEventArgs("Value"));
			}
		}
	}
}